package com.emperor.cashier.app;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.CoolBar;
import org.eclipse.swt.widgets.CoolItem;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.emperor.core.app.App;
import com.emperor.core.app.AppBase;
import com.emperor.core.app.AppConstant;
import com.emperor.core.logic.BizModel;
import com.emperor.core.logic.ReportDataSource;
import com.emperor.course.app.CourseAppCtrl;
import com.emperor.course.logic.Course;
import com.emperor.course.logic.CourseModel;
import com.emperor.course.logic.CourseProduct;
import com.emperor.course.logic.CourseProductModel;
import com.emperor.customer.app.CustomerAppCtrl;
import com.emperor.customer.logic.Customer;
import com.emperor.customer.logic.CustomerModel;
import com.emperor.employee.app.EmployeeAppCtrl;
import com.emperor.employee.logic.Employee;
import com.emperor.employee.logic.EmployeeModel;
import com.emperor.inventory.app.InventoryAppCtrl;
import com.emperor.product.app.ProductAppNew;
import com.emperor.product.logic.Product;
import com.emperor.product.logic.ProductModel;
import com.emperor.productlog.logic.ProductLog;
import com.emperor.productlog.logic.ProductLogModel;
import com.emperor.receipt.app.ReceiptAppCtrl;
import com.emperor.receipt.logic.Receipt;
import com.emperor.receipt.logic.ReceiptModel;
import com.emperor.report.app.ReportAppCtrl;
import com.emperor.role.logic.Role;
import com.emperor.transaction.logic.Transaction;
import com.emperor.transaction.logic.TransactionModel;
import com.emperor.treatment.app.TreatmentAppCtrl;
import com.emperor.treatment.logic.Treatment;
import com.emperor.treatment.logic.TreatmentModel;
import com.emperor.user.logic.User;
import com.emperor.user.logic.UserModel;
import com.emperor.util.DateFormatter;
import com.emperor.util.HibernateUtil;
import com.emperor.util.ReportUtil;
import com.emperor.work.app.WorkAppCtrl;
import com.swtdesigner.SWTResourceManager;

public class CashierAppForm extends AppBase implements App {

	private Label rcpNoLabel;
	private Button resetButton_1;
	private ToolBar toolBar;
	private Button resetButton;
	private Button nextTransactionButton;
	private Group paymentMethodGroup;
	private Button retrieveCustomerButton;
	private Composite composite;
	private Button addButton_1;
	private Button addButton;
	private Button useCustomerDiscountButton;
	private Combo combo;
	private Text custcodeText;
	private Text qtyText;
	private Text skuText;
	private Table table;
	private Text changeText;
	private Text paidText;
	private Text text;
	protected Shell shell;
	protected User user;
	protected Product product;
	protected Course course;
	protected Treatment treatment;
	protected Session session;
	protected Receipt receipt;
	protected Customer customer;
	protected List<Transaction> transactions;
	protected Double total;
	protected String rcpcode;
	protected Integer codeid;
	public static Logger log = Logger.getLogger(CashierAppForm.class);
	private DecimalFormat df0, df2;
	private Double specialDiscount;

	public CashierAppForm() {
		super();
	}

	public CashierAppForm(Map<String, Object> params) {
		super();
		this.params = params;
	}

	/**
	 * Launch the application
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			CashierAppForm window = new CashierAppForm();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window
	 */
	public void open() {
		final Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

	/**
	 * Create contents of the window
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setBackgroundImage(SWTResourceManager.getImage(
				CashierAppForm.class, "/img/main.jpg"));

		shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
		shell.setImage(SWTResourceManager.getImage(CashierAppForm.class,
				"/img/iMac OSX.png"));
		shell.setSize(1280, 800);
		shell.setText("Cashier");

		initScreen(shell, getParams());

		setTransactions(new ArrayList<Transaction>());
		setCustomer(new CustomerModel());

		session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		final Label messageLabel = new Label(shell, SWT.NONE);
		messageLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		messageLabel.setText("Please key in the Product SKU and click Add");
		messageLabel.setBounds(10, 50, 456, 35);

		final Label employeeLabel = new Label(shell, SWT.NONE);
		employeeLabel.setForeground(SWTResourceManager.getColor(128, 0, 0));
		employeeLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.BOLD));
		employeeLabel.setText("Employee");
		employeeLabel.setBounds(919, 216, 80, 20);

		final Label employeeNameLabel = new Label(shell, SWT.NONE);
		employeeNameLabel.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 11, SWT.NORMAL));
		employeeNameLabel.setText("Employee Name");
		employeeNameLabel.setBounds(919, 242, 225, 20);

		final Label employeeLabel_1 = new Label(shell, SWT.NONE);
		employeeLabel_1.setBounds(919, 313, 80, 20);
		employeeLabel_1.setForeground(SWTResourceManager.getColor(128, 0, 0));
		employeeLabel_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.BOLD));
		employeeLabel_1.setText("Customer");

		final Label totalLabel = new Label(shell, SWT.NONE);
		totalLabel.setBounds(587, 547, 80, 40);
		totalLabel.setForeground(SWTResourceManager.getColor(0, 0, 128));
		totalLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 24, SWT.BOLD));
		totalLabel.setText("Total");
		//
		if (getParams().get(AppConstant.USER) != null) {
			setUser((User) getParams().get(AppConstant.USER));
		}

		text = new Text(shell, SWT.BORDER);
		text.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI",
				24, SWT.NORMAL));
		text.setBounds(673, 545, 215, 40);

		paidText = new Text(shell, SWT.BORDER);
		paidText.addFocusListener(new FocusAdapter() {
			public void focusLost(final FocusEvent e) {
				doCalculateChange();
			}
		});
		paidText.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 20, SWT.NORMAL));
		paidText.setBounds(717, 591, 171, 40);

		final Label paidLabel = new Label(shell, SWT.NONE);
		paidLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 20, SWT.NORMAL));
		paidLabel.setText("Paid");
		paidLabel.setBounds(587, 594, 55, 35);

		final Label paidLabel_1 = new Label(shell, SWT.NONE);
		paidLabel_1.setBackground(Display.getCurrent().getSystemColor(
				SWT.COLOR_WHITE));
		paidLabel_1.setBounds(587, 640, 95, 35);
		paidLabel_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 20, SWT.NORMAL));
		paidLabel_1.setText("Change");

		changeText = new Text(shell, SWT.BORDER);
		changeText.setBounds(717, 637, 171, 40);
		changeText.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 20, SWT.NORMAL));

		useCustomerDiscountButton = new Button(shell, SWT.CHECK);
		useCustomerDiscountButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				if (useCustomerDiscountButton.getSelection()) {
					checkTableItems(table, true);
				} else {
					checkTableItems(table, false);
				}

				doRecalculateTransaction(table, useCustomerDiscountButton);
				doPopulateTable(table);
				doCalculateTotal();
				doCalculateChange();
			}
		});
		useCustomerDiscountButton.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));
		useCustomerDiscountButton.setText("Use Customer Discount");
		useCustomerDiscountButton.setBounds(10, 150, 240, 20);

		table = new Table(shell, SWT.CHECK | SWT.FULL_SELECTION | SWT.BORDER);
		table.addMouseListener(new MouseAdapter() {
			public void mouseDoubleClick(final MouseEvent e) {

				if (useCustomerDiscountButton.getSelection()
						&& table.getSelection() != null
						&& table.getSelection().length > 0) {
					TableItem[] items = table.getSelection();
					for (int i = 0; i < items.length; i++) {
						TableItem item = items[i];
						if (item.getData() != null) {
							int index = ((Integer) item.getData()).intValue();
							if (index < getTransactions().size()) {

								Transaction dialogTransaction = getTransactions()
										.get(index);
								getParams()
										.put(CashierAppDiscountDialog.DIALOG_TRANSACTION,
												dialogTransaction);
								CashierAppDiscountDialog dialog = new CashierAppDiscountDialog(
										getShell(), SWT.ICON_INFORMATION,
										getParams());
								dialog.open();
								if (getParams().get(dialog.SPECIAL_PRICE) != null) {
									List<Transaction> transactions = new ArrayList<Transaction>();
									int count = 0;
									for (Iterator<Transaction> iter = getTransactions()
											.iterator(); iter.hasNext();) {
										Transaction transaction = iter.next();

										if (count == index) {
											Double specialprice = new Double(
													0.0);
											Double discount = new Double(0.0);
											try {
												specialprice = new Double(
														(String) getParams()
																.get(dialog.SPECIAL_PRICE));
												discount = new Double(
														(String) getParams()
																.get(dialog.DISCOUNT));
											} catch (Exception nfex) {
											}
											transaction.setDiscount(discount);
											transaction.setCustdiscount(true);
											transaction
													.setSpecialprice(specialprice);
										}

										transactions.add(transaction);
										count++;
									}

									setTransactions(transactions);
									getParams().put(dialog.SPECIAL_PRICE, null);
									getParams().put(dialog.DISCOUNT, null);
								} else if (getParams().get(dialog.DISCOUNT) != null) {
									Double discount = new Double(10.0);
									try {
										discount = new Double(
												(String) getParams().get(
														dialog.DISCOUNT));
									} catch (Exception nfex) {
									}
									List<Transaction> transactions = new ArrayList<Transaction>();

									int count = 0;
									for (Iterator<Transaction> iter = getTransactions()
											.iterator(); iter.hasNext();) {
										Transaction transaction = iter.next();

										if (count == index) {
											transaction.setDiscount(discount);
											transaction.setCustdiscount(true);
											transaction.setSpecialprice(null);
										}

										transactions.add(transaction);
										count++;
									}

									setTransactions(transactions);
									getParams().put(dialog.DISCOUNT, null);
									getParams().put(dialog.SPECIAL_PRICE, null);
								}

								item.setChecked(true);
								getParams()
										.put(dialog.DIALOG_TRANSACTION, null);
							}
						}
					}

					doRecalculateTransaction(table, useCustomerDiscountButton);
					doPopulateTable(table);
					doCalculateTotal();
					doCalculateChange();
				}
			}
		});
		table.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				if (e.detail == SWT.CHECK) {
					doRecalculateTransaction(table, useCustomerDiscountButton);
					doPopulateTable(table);
					doCalculateTotal();
					doCalculateChange();
				}
			}
		});
		table.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI",
				12, SWT.NORMAL));
		table.setLinesVisible(true);
		table.setHeaderVisible(true);
		table.setBounds(10, 200, 878, 339);

		final TableColumn newColumnTableColumn_7 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_7.setWidth(37);
		newColumnTableColumn_7.setText("D.");

		final TableColumn newColumnTableColumn = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn.setWidth(57);
		newColumnTableColumn.setText("No.");

		final TableColumn newColumnTableColumn_1 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_1.setWidth(156);
		newColumnTableColumn_1.setText("SKU");

		final TableColumn newColumnTableColumn_2 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_2.setWidth(269);
		newColumnTableColumn_2.setText("Item");

		final TableColumn newColumnTableColumn_3 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_3.setWidth(73);
		newColumnTableColumn_3.setText("U/Price");

		final TableColumn newColumnTableColumn_4 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_4.setWidth(53);
		newColumnTableColumn_4.setText("Discount");

		final TableColumn newColumnTableColumn_5 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_5.setWidth(71);
		newColumnTableColumn_5.setText("Quantity");

		final TableColumn newColumnTableColumn_8 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_8.setWidth(61);
		newColumnTableColumn_8.setText("Color");

		final TableColumn newColumnTableColumn_6 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_6.setWidth(84);
		newColumnTableColumn_6.setText("SubTotal");

		final Label skuLabel = new Label(shell, SWT.NONE);
		skuLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		skuLabel.setText("SKU");
		skuLabel.setBounds(10, 87, 46, 23);

		skuText = new Text(shell, SWT.BORDER);
		skuText.addKeyListener(new KeyAdapter() {
			public void keyPressed(final KeyEvent e) {
				if (e.character == SWT.LF || e.character == SWT.CR) {
					qtyText.forceFocus();
				}
			}
		});
		skuText.setBounds(62, 87, 260, 25);
		skuText.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));

		qtyText = new Text(shell, SWT.BORDER);
		qtyText.addKeyListener(new KeyAdapter() {
			public void keyPressed(final KeyEvent e) {
				if (e.character == SWT.LF || e.character == SWT.CR) {
					doAddProduct(skuText.getText());
					skuText.forceFocus();
				}
			}
		});
		qtyText.setBounds(431, 87, 80, 25);
		qtyText.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));

		final Label skuLabel_1 = new Label(shell, SWT.NONE);
		skuLabel_1.setBounds(346, 87, 79, 35);
		skuLabel_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		skuLabel_1.setText("Quantity");

		addButton = new Button(shell, SWT.NONE);
		addButton.setImage(SWTResourceManager.getImage(CashierAppForm.class,
				"/img/Symbol-Add.png"));
		addButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				doAddProduct(skuText.getText());

			}
		});
		addButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.BOLD));
		addButton.setText("Add");
		addButton.setBounds(328, 140, 82, 40);

		addButton_1 = new Button(shell, SWT.NONE);
		addButton_1.setImage(SWTResourceManager.getImage(CashierAppForm.class,
				"/img/Symbol-Restricted.png"));
		addButton_1.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				doDeleteTransaction();
			}
		});
		addButton_1.setBounds(416, 140, 95, 40);
		addButton_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.BOLD));
		addButton_1.setText("Delete");

		composite = new Composite(shell, SWT.NONE);
		composite.setBackgroundMode(SWT.INHERIT_DEFAULT);
		composite.setBounds(919, 433, 343, 174);

		final Label customerCodeLabel_1 = new Label(composite, SWT.NONE);
		customerCodeLabel_1.setBounds(10, 10, 140, 20);
		customerCodeLabel_1.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));
		customerCodeLabel_1.setText("Customer Discount");

		final Label customerCodeLabel_1_1 = new Label(composite, SWT.NONE);
		customerCodeLabel_1_1.setToolTipText("cust_discount");
		customerCodeLabel_1_1.setBounds(10, 36, 205, 20);
		customerCodeLabel_1_1.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));

		final Label customerCodeLabel_1_2 = new Label(composite, SWT.NONE);
		customerCodeLabel_1_2.setBounds(10, 62, 140, 20);
		customerCodeLabel_1_2.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));
		customerCodeLabel_1_2.setText("Customer Name");

		final Label customerCodeLabel_1_1_1 = new Label(composite, SWT.NONE);
		customerCodeLabel_1_1_1.setBounds(10, 89, 205, 20);
		customerCodeLabel_1_1_1.setToolTipText("cust_name");
		customerCodeLabel_1_1_1.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));

		final Label customerCodeLabel_1_2_1 = new Label(composite, SWT.NONE);
		customerCodeLabel_1_2_1.setBounds(10, 115, 140, 20);
		customerCodeLabel_1_2_1.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));
		customerCodeLabel_1_2_1.setText("Join Date");

		final Label customerCodeLabel_1_2_1_1 = new Label(composite, SWT.NONE);
		customerCodeLabel_1_2_1_1.setToolTipText("cust_joindate");
		customerCodeLabel_1_2_1_1.setBounds(10, 141, 205, 20);
		customerCodeLabel_1_2_1_1.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));

		final Label customerCodeLabel = new Label(shell, SWT.NONE);
		customerCodeLabel.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));
		customerCodeLabel.setText("Customer Code / IC / Name");
		customerCodeLabel.setBounds(919, 339, 240, 20);

		custcodeText = new Text(shell, SWT.BORDER);
		custcodeText.addKeyListener(new KeyAdapter() {
			public void keyPressed(final KeyEvent e) {
				if (e.character == SWT.LF || e.character == SWT.CR) {
					doRetrieveCustomer(custcodeText);
					if (getCustomer().getId() != null) {
						useCustomerDiscountButton.setEnabled(true);
					}
					doRecalculateTransaction(table, useCustomerDiscountButton);
					doDisplayCustomer(composite);
					doPopulateTable(table);
					doCalculateTotal();
					doCalculateChange();
				}
			}
		});
		custcodeText.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		custcodeText.setBounds(919, 366, 343, 25);

		retrieveCustomerButton = new Button(shell, SWT.NONE);
		retrieveCustomerButton.setImage(SWTResourceManager.getImage(
				CashierAppForm.class, "/img/Zoom-in.png"));
		retrieveCustomerButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				doRetrieveCustomer(custcodeText);
				if (getCustomer().getId() != null) {
					useCustomerDiscountButton.setEnabled(true);
				}
				doRecalculateTransaction(table, useCustomerDiscountButton);
				doDisplayCustomer(composite);
				doPopulateTable(table);
				doCalculateTotal();
				doCalculateChange();
			}
		});
		retrieveCustomerButton.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));
		retrieveCustomerButton.setText("Search");
		retrieveCustomerButton.setBounds(919, 397, 90, 30);

		paymentMethodGroup = new Group(shell, SWT.NONE);
		paymentMethodGroup.setBackground(Display.getCurrent().getSystemColor(
				SWT.COLOR_WHITE));
		paymentMethodGroup.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));
		paymentMethodGroup.setText("Payment Method");
		paymentMethodGroup.setBounds(517, 87, 184, 107);

		final Button cashButton = new Button(paymentMethodGroup, SWT.RADIO);
		cashButton.setToolTipText("pay.cash");
		cashButton.setSelection(true);
		cashButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		cashButton.setText("Cash");
		cashButton.setBounds(10, 35, 105, 20);

		final Button cashButton_1 = new Button(paymentMethodGroup, SWT.RADIO);
		cashButton_1.setToolTipText("pay.visa");
		cashButton_1.setBounds(10, 56, 60, 20);
		cashButton_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		cashButton_1.setText("Visa");

		final Button cashButton_1_1 = new Button(paymentMethodGroup, SWT.RADIO);
		cashButton_1_1.setToolTipText("pay.master");
		cashButton_1_1.setBounds(10, 77, 164, 20);
		cashButton_1_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		cashButton_1_1.setText("MasterCard");

		nextTransactionButton = new Button(shell, SWT.NONE);
		nextTransactionButton.setImage(SWTResourceManager.getImage(
				CashierAppForm.class, "/img/Save.png"));
		nextTransactionButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				doSaveTransactions(text.getText(), paidText.getText(),
						changeText.getText(), paymentMethodGroup, messageLabel);
			}
		});
		nextTransactionButton.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 14, SWT.BOLD));
		nextTransactionButton.setText("Print and Save");
		nextTransactionButton.setBounds(954, 624, 190, 51);

		combo = new Combo(shell, SWT.NONE);
		combo.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				changeUser();
			}
		});
		combo.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI",
				12, SWT.NORMAL));
		combo.setBounds(919, 268, 343, 28);

		final Label timerLabel = new Label(shell, SWT.NONE);
		timerLabel.setForeground(SWTResourceManager.getColor(0, 0, 128));
		timerLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 14, SWT.NORMAL));
		timerLabel.setText("12:00:00 PM");
		timerLabel.setBounds(1112, 0, 140, 40);

		final SimpleDateFormat sdf = new SimpleDateFormat(DateFormatter.HHMMSS);
		final Runnable timer = new Runnable() {
			public void run() {
				timerLabel.setText(sdf.format(new Date()));
				getShell().getDisplay().timerExec(1000, this);
			}
		};
		getShell().getDisplay().timerExec(1000, timer);
		getShell().addShellListener(new ShellAdapter() {
			public void shellClosed(final ShellEvent e) {
				getShell().getDisplay().timerExec(-1, timer);
			}
		});

		resetButton = new Button(shell, SWT.NONE);
		resetButton.setImage(SWTResourceManager.getImage(CashierAppForm.class,
				"/img/Refresh.png"));
		resetButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				getShell().close();
			}
		});
		resetButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 14, SWT.BOLD));
		resetButton.setText("Reset");
		resetButton.setBounds(1160, 624, 102, 51);

		df0 = new DecimalFormat();
		df0.applyPattern("##########.##");
		df0.setMinimumFractionDigits(0);
		df0.setMaximumFractionDigits(0);

		df2 = new DecimalFormat();
		df2.applyPattern("##########.##");
		df2.setMinimumFractionDigits(2);
		df2.setMaximumFractionDigits(2);

		final Label rcpCodeLabel = new Label(shell, SWT.NONE);
		rcpCodeLabel.setBounds(707, 140, 181, 40);
		rcpCodeLabel.setForeground(SWTResourceManager.getColor(128, 0, 0));
		rcpCodeLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 16, SWT.BOLD));

		buildMenu();
		populateUser(employeeNameLabel);
		populateCombo(combo);
		populateRcpCode(rcpCodeLabel);

		resetButton_1 = new Button(shell, SWT.NONE);
		resetButton_1.setVisible(false);
		resetButton_1.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				printReceipt(text, paidText, changeText, paymentMethodGroup);
			}
		});
		resetButton_1.setImage(SWTResourceManager.getImage(
				CashierAppForm.class, "/img/Printer.png"));
		resetButton_1.setBounds(954, 684, 70, 30);
		resetButton_1.setFont(SWTResourceManager.getFont("", 12, SWT.NONE));
		resetButton_1.setText("Print");

		rcpNoLabel = new Label(shell, SWT.NONE);
		rcpNoLabel.setBounds(707, 87, 181, 40);
		rcpNoLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 20, SWT.NORMAL));
		rcpNoLabel.setBackground(SWTResourceManager.getColor(255, 255, 255));
		rcpNoLabel.setText("Receipt No");
		shell.setTabList(new Control[] { skuText, qtyText, addButton,
				addButton_1, text, paidText, changeText,
				useCustomerDiscountButton, table, composite, custcodeText,
				retrieveCustomerButton, paymentMethodGroup,
				nextTransactionButton, combo, resetButton, toolBar,
				resetButton_1, rcpNoLabel });
	}

	private void buildMenu() {
		toolBar = new ToolBar(shell, SWT.RIGHT);
		toolBar.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 9, SWT.NORMAL));
		toolBar.setBounds(0, 0, 1093, 40);

		if (getUser() != null
				&& getUser().getRole().getName().equals(Role.ROLE_ADMIN)) {
			final ToolItem newItemToolItem = new ToolItem(toolBar, SWT.PUSH);
			newItemToolItem.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(final SelectionEvent e) {
					getParams().put(AppConstant.APPCTRL,
							InventoryAppCtrl.INVENTORY_CTRL);
					getParams().put(AppConstant.ACTION,
							InventoryAppCtrl.INVENTORY_ENQ);
					getShell().close();
				}
			});
			newItemToolItem.setImage(SWTResourceManager.getImage(
					CashierAppForm.class, "/img/Inventory.png"));
			newItemToolItem.setText("Inventory");

			final ToolItem newItemToolItem_3 = new ToolItem(toolBar, SWT.PUSH);
			newItemToolItem_3.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(final SelectionEvent e) {
					getParams().put(AppConstant.APPCTRL,
							CourseAppCtrl.COURSE_CTRL);
					getParams().put(AppConstant.ACTION,
							CourseAppCtrl.COURSE_ENQ);
					getShell().close();
				}
			});
			newItemToolItem_3.setImage(SWTResourceManager.getImage(
					CashierAppForm.class, "/img/Users.png"));
			newItemToolItem_3.setText("Course");

			final ToolItem newItemToolItem_4 = new ToolItem(toolBar, SWT.PUSH);
			newItemToolItem_4.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(final SelectionEvent e) {
					getParams().put(AppConstant.APPCTRL,
							TreatmentAppCtrl.TREATMENT_CTRL);
					getParams().put(AppConstant.ACTION,
							TreatmentAppCtrl.TREATMENT_ENQ);
					getShell().close();
				}
			});
			newItemToolItem_4.setImage(SWTResourceManager.getImage(
					CashierAppForm.class, "/img/Inventory.png"));
			newItemToolItem_4.setText("Treament");

			final ToolItem newItemToolItem_1 = new ToolItem(toolBar, SWT.PUSH);
			newItemToolItem_1.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(final SelectionEvent e) {
					getParams().put(AppConstant.APPCTRL,
							CustomerAppCtrl.CUST_CTRL);
					getParams().put(AppConstant.ACTION,
							CustomerAppCtrl.CUST_ENQ);
					getShell().close();
				}
			});
			newItemToolItem_1.setImage(SWTResourceManager.getImage(
					CashierAppForm.class, "/img/Puma.png"));
			newItemToolItem_1.setText("Customer");

			final ToolItem newItemToolItem_2 = new ToolItem(toolBar, SWT.PUSH);
			newItemToolItem_2.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(final SelectionEvent e) {
					getParams().put(AppConstant.APPCTRL,
							EmployeeAppCtrl.EMP_CTRL);
					getParams()
							.put(AppConstant.ACTION, EmployeeAppCtrl.EMP_ENQ);
					getShell().close();
				}
			});
			newItemToolItem_2.setImage(SWTResourceManager.getImage(
					CashierAppForm.class, "/img/Users.png"));
			newItemToolItem_2.setText("Employee");
		}

		final ToolItem newItemToolItem_3 = new ToolItem(toolBar, SWT.PUSH);
		newItemToolItem_3.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				getParams().put(AppConstant.APPCTRL, WorkAppCtrl.WORK_CTRL);
				getParams().put(AppConstant.ACTION, WorkAppCtrl.WORK_NEW);
				getShell().close();
			}
		});
		newItemToolItem_3.setImage(SWTResourceManager.getImage(
				CashierAppForm.class, "/img/Work.png"));
		newItemToolItem_3.setText("Worksheet");

		final ToolItem newItemToolItem_4 = new ToolItem(toolBar, SWT.PUSH);
		newItemToolItem_4.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				getParams().put(AppConstant.APPCTRL,
						ReceiptAppCtrl.RECEIPT_CTRL);
				getParams().put(AppConstant.ACTION, ReceiptAppCtrl.RECEIPT_ENQ);
				getShell().close();
			}
		});
		newItemToolItem_4.setImage(SWTResourceManager.getImage(
				CashierAppForm.class, "/img/Puma.png"));
		newItemToolItem_4.setText("Receipt");

		final ToolItem newItemToolItem_5 = new ToolItem(toolBar, SWT.PUSH);
		newItemToolItem_5.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				getParams().put(AppConstant.APPCTRL, ReportAppCtrl.REPORT_CTRL);
				getParams().put(AppConstant.ACTION, ReportAppCtrl.REPORT_ENQ);
				getShell().close();
			}
		});
		newItemToolItem_5.setImage(SWTResourceManager.getImage(
				CashierAppForm.class, "/img/Report.png"));
		newItemToolItem_5.setText("Report");

		final ToolItem newItemToolItem_6 = new ToolItem(toolBar, SWT.PUSH);
		newItemToolItem_6.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				gotoHelp(getShell(), getParams());
			}
		});
		newItemToolItem_6.setImage(SWTResourceManager.getImage(
				CashierAppForm.class, "/img/Help.png"));
		newItemToolItem_6.setText("Help");

		final ToolItem newItemToolItem_7 = new ToolItem(toolBar, SWT.PUSH);
		newItemToolItem_7.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				getParams().put(AppConstant.APPCTRL, null);
				getParams().put(AppConstant.USER, null);
				getShell().close();
			}
		});
		newItemToolItem_7.setImage(SWTResourceManager.getImage(
				CashierAppForm.class, "/img/Logout.png"));
		newItemToolItem_7.setText("Logout");

		/*
		 * final ToolItem newItemToolItem_7 = new ToolItem(toolBar, SWT.PUSH);
		 * newItemToolItem_7.addSelectionListener(new SelectionAdapter() {
		 * public void widgetSelected(final SelectionEvent e) {
		 * getParams().put(AppConstant.ONLINE, new Boolean(false));
		 * getShell().close(); } });
		 * newItemToolItem_7.setImage(SWTResourceManager.getImage(
		 * CashierAppForm.class, "/img/Symbol-Delete.png"));
		 * newItemToolItem_7.setText("Exit");
		 */
	}

	private void populateUser(Label label) {
		try {
			label.setText(getUser().getEmployee().getName());
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}

	private Product doRetrieveProduct(String sku) {
		Product product = new ProductModel();
		try {
			if (!StringUtils.isEmpty(sku)) {
				List<Product> products = session
						.createCriteria(ProductModel.class)
						.add(Expression.eq(Product.FLD_SKU, sku))
						.add(Expression.eq(Product.FLD_STATUS,
								AppConstant.STATUS_ACTIVE)).list();
				if (products != null && !products.isEmpty()) {
					setProduct(products.get(0));
					product = products.get(0);
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return product;
	}

	private Course doRetrieveCourse(String sku) {
		Course course = new CourseModel();
		try {
			if (!StringUtils.isEmpty(sku)) {
				List<Course> courses = session
						.createCriteria(CourseModel.class)
						.add(Restrictions.eq(Course.FLD_SKU, sku))
						.add(Restrictions.eq(Course.FLD_STATUS,
								AppConstant.STATUS_ACTIVE)).list();
				if (courses != null && !courses.isEmpty()) {
					course = courses.get(0);
					setCourse(course);
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return course;
	}

	private Treatment doRetrieveTreatment(String sku) {
		Treatment treatment = new TreatmentModel();
		try {
			if (!StringUtils.isEmpty(sku)) {
				List<Treatment> treatments = session
						.createCriteria(TreatmentModel.class)
						.add(Restrictions.eq(Treatment.FLD_SKU, sku))
						.add(Restrictions.eq(Treatment.FLD_STATUS,
								AppConstant.STATUS_ACTIVE)).list();
				if (treatments != null && !treatments.isEmpty()) {
					treatment = treatments.get(0);
					setTreatment(treatment);
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return treatment;
	}

	public void doAddTransactions(BizModel item, Double quantity, Button button) {
		int itemType = 0; // 1-Product, 2-Course, 3-Treatment
		Product product = null;
		Course course = null;
		Treatment treatment = null;
		Double itemPrice = new Double(0), itemCost = new Double(0), itemDiscount = new Double(
				0);
		if (item instanceof Product) {
			itemType = Transaction.TYPE_PRODUCT;
			product = (Product) item;
			itemPrice = product.getPrice();
			itemCost = product.getCost();
			itemDiscount = product.getDiscount();
		} else if (item instanceof Course) {
			itemType = Transaction.TYPE_COURSE;
			course = (Course) item;
			itemPrice = course.getPrice();
			itemCost = course.getCost();
			itemDiscount = course.getDiscount();
		} else if (item instanceof Treatment) {
			itemType = Transaction.TYPE_TREATMENT;
			treatment = (Treatment) item;
			itemPrice = treatment.getPrice();
			itemCost = treatment.getCost();
			itemDiscount = treatment.getDiscount();
		}

		try {
			Transaction transaction = new TransactionModel();
			if (quantity != null) {
				switch (itemType) {
				case 2:
					transaction.setCourse(course);
					transaction.setType(Transaction.TYPE_COURSE);
					break;
				case 3:
					transaction.setTreatment(treatment);
					transaction.setType(Transaction.TYPE_TREATMENT);
					break;
				default:
					transaction.setProduct(product);
					transaction.setWeight(product.getWeight());
					transaction.setWeightuom(product.getWeightuom());
					transaction.setType(Transaction.TYPE_PRODUCT);
					break;
				}

				transaction.setStatus(AppConstant.STATUS_ACTIVE);
				transaction.setPrice(itemPrice);
				transaction.setQuantity(quantity);
				transaction.setCustdiscount(button.getSelection());

				if (itemCost == null) {
					transaction.setTotalcost(0);
				} else {
					transaction.setTotalcost(new BigDecimal(itemCost).multiply(
							new BigDecimal(quantity)).doubleValue());
				}

				BigDecimal subtotal = new BigDecimal(0.0);
				subtotal.setScale(2, BigDecimal.ROUND_HALF_UP);

				Double discount = 0.0;

				if (button.getSelection()) {
					transaction.setDiscount(getCustomer().getDiscount());
					discount = ((transaction.getPrice() * getCustomer()
							.getDiscount()) / 100);
					transaction.setCustdiscount(true);
				} else if (getCustomer().getId() == null
						&& button.getSelection()) {
					transaction.setDiscount(10.0);
					discount = ((transaction.getPrice() * 10.0) / 100);
					transaction.setCustdiscount(true);
				} else {
					transaction.setDiscount(itemDiscount);
					discount = ((transaction.getPrice() * transaction
							.getDiscount()) / 100);
					transaction.setCustdiscount(false);
				}

				subtotal = new BigDecimal(transaction.getPrice())
						.subtract(new BigDecimal(discount));
				subtotal = subtotal.multiply(new BigDecimal(transaction
						.getQuantity()));
				transaction.setSubtotal(df2.format(subtotal.doubleValue()));

				List<Transaction> transactions = getTransactions();
				transactions.add(transaction);
				setTransactions(transactions);
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}

	public void doPopulateTable(Table table) {
		table.clearAll();
		table.removeAll();
		table.redraw();
		try {
			if (getTransactions() != null && !getTransactions().isEmpty()) {
				int rowCount = 0;
				Product product = null;
				Course course = null;
				Treatment treatment = null;
				String sku = "", name = "";
				for (Iterator<Transaction> iter = getTransactions().iterator(); iter
						.hasNext();) {
					Transaction transaction = iter.next();
					int type = transaction.getType();
					switch (type) {
					case 2:
						course = transaction.getCourse();
						sku = course.getSku();
						name = course.getName();
						break;
					case 3:
						treatment = transaction.getTreatment();
						sku = treatment.getSku();
						name = treatment.getName();
						break;
					default:
						product = transaction.getProduct();
						sku = product.getSku();
						name = product.getName();
						break;
					}

					rowCount++;
					TableItem item = new TableItem(table, SWT.BORDER);
					// TODO has to be dynamic between customer
					item.setText(new String[] { "", rowCount + ".", sku, name,
							df2.format(transaction.getPrice()),
							df0.format(transaction.getDiscount()),
							df0.format(transaction.getQuantity()), "",
							df2.format(transaction.getSubtotal()) });
					item.setData(rowCount - 1);

					if (getCustomer().getId() != null) {
						if (transaction.getCustdiscount()) {
							item.setChecked(true);
						}
					}

					if (getCustomer().getId() != null
							&& transaction.getCustdiscount()) {
						item.setChecked(true);
					} else if (useCustomerDiscountButton.getSelection()
							&& transaction.getCustdiscount()) {
						item.setChecked(true);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		}
	}

	private void doCalculateTotal() {
		BigDecimal total = new BigDecimal(0.0);
		total.setScale(2, BigDecimal.ROUND_HALF_UP);

		if (getTransactions() != null && !getTransactions().isEmpty()) {
			for (Iterator<Transaction> iter = getTransactions().iterator(); iter
					.hasNext();) {
				Transaction transaction = iter.next();
				// total += transaction.getSubtotal();
				total = total.add(new BigDecimal(transaction.getSubtotal()));
			}
		}

		getText().setText(df2.format(total.doubleValue()));
		setTotal(total.doubleValue());
	}

	private void doDeleteTransaction() {
		if (getTransactions() != null && !getTransactions().isEmpty()) {
			TableItem[] items = getTable().getSelection();
			if (items != null && items.length > 0) {
				for (int i = 0; i < items.length; i++) {
					TableItem item = items[i];
					int index = ((Integer) item.getData()).intValue();
					if (index > -1 && index < getTransactions().size()) {
						getTransactions().remove(index);
						doPopulateTable(getTable());
						doCalculateTotal();
						doCalculateChange();
					}
				}
			}
		}
	}

	private void doCalculateChange() {
		if (getTotal() != null && getPaidText().getText().length() > 0) {
			BigDecimal paid = new BigDecimal(getPaidText().getText());
			paid.setScale(2, BigDecimal.ROUND_HALF_UP);
			getPaidText().setText(df2.format(paid.doubleValue()));
			BigDecimal change = paid.subtract(new BigDecimal(getTotal()));
			change.setScale(2, BigDecimal.ROUND_HALF_UP);
			getChangeText().setText(df2.format(change.doubleValue()));
		}
	}

	private void doRetrieveCustomer(Text text) {
		Customer customer = new CustomerModel();

		if (text.getText() != null && text.getText().length() > 0) {
			Criterion criCode = Restrictions.eq(Customer.FLD_CODE, text.getText());
			Criterion criIc = Restrictions.eq(Customer.FLD_IC, text.getText());
			Criterion criName = Restrictions.like(Customer.FLD_NAME, text.getText(), MatchMode.ANYWHERE);
			Disjunction disjunction = Restrictions.disjunction();
			disjunction.add(criIc).add(criName).add(criCode);
			List<Customer> customers = session
					.createCriteria(CustomerModel.class)
					.add(disjunction).list();
			if (customers != null && !customers.isEmpty()) {
				customer = (Customer) customers.get(0);
			} else {
				message(getShell(), "No customer found.",
						"No customer found.");
			}
		}

		if (customer.getId() != null) {
			setCustomer(customer);
		}
	}

	private void doDisplayCustomer(Composite composite) {
		if (getCustomer().getId() != null) {
			setControls(composite, "cust", getCustomer());
		}
	}

	private void doClearAdd(Text skuText, Text qtyText) {
		skuText.setText("");
		qtyText.setText("");
	}

	private int doSaveTransactions(String total, String paid, String change,
			Group group, Label messageLabel) {
		int rowCount = 0;
		try {
			Receipt receipt = new ReceiptModel();
			if (getCustomer().getId() != null) {
				receipt.setCustomer(getCustomer());
			} else if (!"".equals(custcodeText.getText().trim())) {
				receipt.setCustname(custcodeText.getText());
			}
			receipt.setCode(getRcpcode());
			receipt.setStatus(AppConstant.STATUS_ACTIVE);
			receipt.setTotal(total);
			receipt.setChange(change);
			receipt.setPaid(paid);
			receipt.setPaymethod(getRadioText(group));

			// do validation
			List<String> errors = validateReceipt(receipt, getTransactions());
			if (errors.isEmpty()) {

				receipt = (Receipt) preAdd(receipt, getParams());
				receipt.setCodeid(getCodeid());
				// if current logged in user switch to another user
				// in the combo, it is recorded inside updby which means
				// crtby and updby for the receipt is different person
				receipt.setUpdby(getUser().getEmployee().getId());

				try {

					session.beginTransaction();
					log.debug(receipt.getClass().getSimpleName() + " : "
							+ receipt.getValues().toString());
					if (receipt.getCustomer() != null) {
						log.debug(receipt.getCustomer().getValues().toString());
					}
					session.save(receipt);
					log.debug(receipt.getClass().getSimpleName() + " : "
							+ receipt.getValues().toString());

					if (receipt.getId() != null) {
						rowCount++;
						if (getTransactions() != null
								&& !getTransactions().isEmpty()) {
							for (Iterator<Transaction> iter = getTransactions()
									.iterator(); iter.hasNext();) {

								Transaction transaction = iter.next();

								transaction = (Transaction) preAdd(transaction,
										getParams());
								transaction.setReceipt(receipt);
								session.save(transaction);

								if (transaction.getId() != null) {
									// remove from inventory
									removeInventory(session, transaction);
								}
								log.debug(transaction.getClass()
										.getSimpleName()
										+ " : "
										+ transaction.getValues().toString());
							}
						}
					}

					session.getTransaction().commit();
				} catch (Exception e) {
					session.getTransaction().rollback();
					log.error(e.getMessage(), e);
				}
			} else {
				message(getShell(), "Save Error.", errors, SWT.ICON_ERROR
						| SWT.OK);
			}

			if (rowCount > 0) {
				// printReceipt(text, paidText, changeText, group);
				printReceipt(receipt.getId());
				setCustomer(new CustomerModel());
				setTransactions(new ArrayList<Transaction>());

				getShell().close();
			}
		} catch (Exception e) {
			e.printStackTrace();
			message(getShell(), "Save Error", e.getMessage(), SWT.ICON_ERROR
					| SWT.OK);
			log.error(e.getMessage(), e);
		}

		return rowCount;
	}

	private void removeInventory(Session session, Transaction transaction)
			throws Exception {
		switch (transaction.getType()) {
		case Transaction.TYPE_COURSE:
			Course course = transaction.getCourse();
			Criteria cris = session.createCriteria(CourseProductModel.class);
			if (course != null && course.getId() != null) {
				cris.add(Restrictions.eq(CourseProduct.FLD_COURSE, course));
			}

			cris.add(Restrictions.eq(CourseProduct.FLD_STATUS,
					AppConstant.STATUS_ACTIVE));
			List<CourseProduct> courseProducts = cris.list();

			for (Iterator<CourseProduct> iter = courseProducts.iterator(); iter
					.hasNext();) {
				CourseProduct courseProduct = iter.next();

				Product product = courseProduct.getProduct();
				Double xquantity = product.getQuantity();

				product.setQuantity(product.getQuantity()
						- (transaction.getQuantity() * courseProduct
								.getQuantity()));

				session.update(product);
				logProduct(product, getParams(), ProductLog.ACT_STOCK_OUT + "-"
						+ ProductLog.ACT_SALES, transaction, xquantity);
			}

			break;
		case Transaction.TYPE_TREATMENT:
			break;
		default:
			Product product = transaction.getProduct();
			Double xquantity = product.getQuantity();
			product.setQuantity(product.getQuantity()
					- transaction.getQuantity());

			session.update(product);

			logProduct(product, getParams(), ProductLog.ACT_STOCK_OUT + "-"
					+ ProductLog.ACT_SALES, transaction, xquantity);
			break;
		}
	}

	private List<String> validateReceipt(Receipt receipt,
			List<Transaction> transactions) {
		List<String> errors = new ArrayList<String>();

		if (receipt.getTotal() == null) {
			errors.add("Invalid Total Amount. Please key in total.");
		}
		if (receipt.getPaid() == null) {
			errors.add("Invalid Paid Amount. Please key in paid.");
		}

		if (receipt.getPaid() != null && receipt.getTotal() != null) {
			if (receipt.getPaid() < receipt.getTotal()) {
				//errors.add("Insufficient Payment. Please key in correct Paid Amount.");
			}
		}

		if (transactions != null && transactions.isEmpty()) {
			errors.add("No item in this receipt.");
		}
		return errors;
	}

	private String getRadioText(Group group) {
		String result = "";
		if (group != null && group.getChildren() != null) {
			Control[] controls = group.getChildren();
			if (controls != null && controls.length > 0) {
				for (int i = 0; i < controls.length; i++) {
					if (controls[i] instanceof Button) {
						Button button = (Button) controls[i];
						if (button.getSelection()) {
							result = button.getToolTipText();
							break;
						}
					}
				}
			}
		}
		return result;
	}

	private void populateCombo(Combo combo) {
		try {
			List<Employee> employees = session
					.createCriteria(EmployeeModel.class)
					.add(Expression.eq(Employee.FLD_STATUS,
							AppConstant.STATUS_ACTIVE)).list();
			if (employees != null && !employees.isEmpty()) {
				for (Iterator<Employee> iter = employees.iterator(); iter
						.hasNext();) {
					Employee employee = iter.next();
					combo.add(employee.getName());
				}
			}
		} catch (Exception e) {
			log.error("Unable to populate combo.", e);
		}
	}

	public void changeUser() {
		if (combo.getText() != null) {
			try {
				List<Employee> employees = session
						.createCriteria(EmployeeModel.class)
						.add(Expression.and(Expression.eq(Employee.FLD_NAME,
								combo.getText()), Expression.eq(
								Employee.FLD_STATUS, AppConstant.STATUS_ACTIVE)))
						.list();
				if (employees != null && !employees.isEmpty()) {
					List<User> users = session
							.createCriteria(UserModel.class)
							.add(Expression.eq(User.FLD_EMPLOYEE,
									employees.get(0))).list();
					if (users != null && !users.isEmpty()) {
						setUser(users.get(0));
					}
				}
			} catch (Exception e) {
				log.error("Unable to change user.", e);
			}
		}
	}

	private String generateReceiptCode(Integer codeid) {
		StringBuffer sb = new StringBuffer();
		try {
			sb.append("RN");
			if (codeid != null) {
				sb.append(codeid);
			}
		} catch (Exception e) {
			log.error("Unable to generate receipt code.", e);
		}
		return sb.toString();
	}

	private void populateRcpCode(Label label) {
		try {
			Integer codeid = new Integer(Receipt.START_CODEID);
			List<Receipt> receipts = session.createCriteria(ReceiptModel.class)
					.addOrder(Order.desc(Receipt.FLD_ID)).setMaxResults(1)
					.list();
			if (receipts != null && !receipts.isEmpty()) {
				Receipt receipt = receipts.get(0);
				codeid = receipt.getCodeid().intValue() + 1;
			}
			setCodeid(codeid);
			setRcpcode(generateReceiptCode(getCodeid()));
			label.setText(getRcpcode());
		} catch (Exception e) {
			log.error("Unable to populate receipt code.", e);
		}
	}

	private void doRecalculateTransaction(Table table, Button button) {

		try {
			List<Transaction> transactions = new ArrayList<Transaction>();
			TableItem[] items = table.getItems();

			for (int i = 0; i < items.length; i++) {
				TableItem item = items[i];
				if (item.getData() != null) {

					int index = ((Integer) item.getData()).intValue();
					if (index > -1 && index < getTransactions().size()) {
						Transaction transaction = getTransactions().get(index);

						BigDecimal subtotal = new BigDecimal(0.0);
						subtotal.setScale(2, BigDecimal.ROUND_HALF_UP);

						Double discountamt = 0.0;

						if (transaction.getSpecialprice() != null) {
							// trasaction setDiscount and setCustdiscount
							// already done in double click
							discountamt = (transaction.getPrice() - transaction
									.getSpecialprice());

						} else if (getCustomer().getId() != null
								&& item.getChecked()) {
							transaction
									.setDiscount(getCustomer().getDiscount());
							discountamt = ((transaction.getPrice() * getCustomer()
									.getDiscount()) / 100);
							transaction.setCustdiscount(true);
						} else if (getCustomer().getId() == null
								&& item.getChecked()) {
							// transaction setDiscount and setCustdiscount
							// already done in double click
							discountamt = ((transaction.getPrice() * transaction
									.getDiscount()) / 100);
						} else {
							transaction.setDiscount(transaction.getProduct()
									.getDiscount());
							discountamt = ((transaction.getPrice() * transaction
									.getDiscount()) / 100);
							transaction.setCustdiscount(false);
						}

						Double totalDiscountAmt = new BigDecimal(discountamt)
								.multiply(
										new BigDecimal(transaction
												.getQuantity())).doubleValue();
						subtotal = new BigDecimal(transaction.getPrice())
								.subtract(new BigDecimal(discountamt));
						subtotal = subtotal.multiply(new BigDecimal(transaction
								.getQuantity()));
						transaction.setSubtotal(df2.format(subtotal
								.doubleValue()));
						transaction.setDiscountamt(totalDiscountAmt);

						transactions.add(transaction);
					}
				}
			}

			getTransactions().clear();
			setTransactions(transactions);
		} catch (Exception e) {
			log.error("Unable to recalculate transaction.", e);
		}
	}

	private void printReceipt(Text totalText, Text paidText, Text changeText,
			Group paymentMethodGroup) {
		Map params = new HashMap();
		try {
			if (getCustomer().getId() != null) {
				params.put(Customer.class.getSimpleName() + "."
						+ Customer.FLD_NAME, getCustomer().getName());
				params.put(Customer.class.getSimpleName() + "."
						+ Customer.FLD_CODE, getCustomer().getCode());
			}

			if (getUser().getEmployee() != null) {
				params.put(Employee.class.getSimpleName() + "."
						+ Employee.FLD_NAME, getUser().getEmployee().getName());
			}

			params.put(Receipt.class.getSimpleName() + "." + Receipt.FLD_TOTAL,
					new Double(text.getText()));
			params.put(Receipt.class.getSimpleName() + "." + Receipt.FLD_PAID,
					new Double(paidText.getText()));
			params.put(
					Receipt.class.getSimpleName() + "." + Receipt.FLD_CHANGE,
					new Double(changeText.getText()));
			params.put(Receipt.class.getSimpleName() + "."
					+ Receipt.FLD_CRTDATE, new Date());
			params.put(Receipt.class.getSimpleName() + "." + Receipt.FLD_CODE,
					getRcpcode());
			params.put(Receipt.class.getSimpleName() + "."
					+ Receipt.FLD_PAYMETHOD, getRadioText(paymentMethodGroup));

			List list = new ArrayList();

			if (getTransactions() != null && !getTransactions().isEmpty()) {
				Map record = new HashMap();
				for (Iterator<Transaction> iter = getTransactions().iterator(); iter
						.hasNext();) {
					Transaction transaction = iter.next();

					record = new HashMap();
					record.put("Quantity", transaction.getQuantity());
					record.put("Discount", transaction.getDiscount());
					record.put("Subtotal", transaction.getSubtotal());

					switch (transaction.getType()) {
					case Transaction.TYPE_COURSE:
						Course course = transaction.getCourse();
						if (course != null) {
							record.put("Item", course.getName());
							record.put("Price", course.getPrice());
							record.put("SKU", course.getSku());
							record.put("Weight", 0);
							record.put("Weightuom", "");
						}
						break;
					case Transaction.TYPE_TREATMENT:
						Treatment treatment = transaction.getTreatment();
						if (treatment != null) {
							record.put("Item", treatment.getName());
							record.put("Price", treatment.getPrice());
							record.put("SKU", treatment.getSku());
							record.put("Weight", 0);
							record.put("Weightuom", "");
						}
						break;
					default:
						Product product = transaction.getProduct();
						if (product != null) {
							record.put("Item", product.getName());
							record.put("Price", product.getPrice());
							record.put("SKU", product.getSku());
							record.put("Weight", product.getWeight());
							record.put("Weightuom", product.getWeightuom());
						}
						break;
					}

					list.add(record);
				}
			} else {
				Map sample = new HashMap();

				sample.put("Quantity", new Double(0.0));
				sample.put("Item", "Not available");
				sample.put("Price", new Double(0.0));
				sample.put("Discount", new Double(0.0));
				sample.put("Subtotal", new Double(0.0));
				sample.put("SKU", "00000099");
				sample.put("Weight", new Double(0.0));
				sample.put("Weightuom", "ml");

				list.add(sample);
			}

			ReportDataSource dataSource = new ReportDataSource(list);
			ReportUtil.runReceiptPrint("./report/Receipt-Print.jrxml", params,
					dataSource, AppConstant.PRINT_REPORT);
		} catch (Exception e) {
			log.error("Unable to print receipt.", e);
		}
	}

	private void printReceipt(Long receiptId) {
		try {
			Map params = new HashMap();
			params.put("rcp_id", receiptId);
			ReportUtil.runReport("emperor", "root", "password",
					"./report/Receipt-DB-Print.jrxml", params);
		} catch (Exception e) {
			log.error("Unable to print receipt.", e);
		}
	}

	public Shell getShell() {
		return shell;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		if (user != null) {
			this.user = user;
		}
	}

	public Product getProduct() {
		return product;
	}

	public void setProduct(Product product) {
		if (product != null) {
			this.product = product;
		}
	}

	public Course getCourse() {
		return course;
	}

	public void setCourse(Course course) {
		if (course != null) {
			if (course instanceof Course) {
				this.course = (Course) course;
			}
		}
	}

	public Treatment getTreatment() {
		return treatment;
	}

	public void setTreatment(Treatment treatment) {
		if (treatment != null) {
			if (treatment instanceof Treatment) {
				this.treatment = (Treatment) treatment;
			}
		}
	}

	public List<Transaction> getTransactions() {
		return this.transactions;
	}

	public void setTransactions(List<Transaction> transactions) {
		this.transactions = transactions;
	}

	public Receipt getReceipt() {
		return receipt;
	}

	public Text getText() {
		return text;
	}

	public void setText(Text text) {
		this.text = text;
	}

	public void setReceipt(Receipt receipt) {
		if (receipt != null) {
			this.receipt = receipt;
		}
	}

	public Double getTotal() {
		return total;
	}

	public void setTotal(Double total) {
		this.total = total;
	}

	public Text getChangeText() {
		return changeText;
	}

	public void setChangeText(Text changeText) {
		this.changeText = changeText;
	}

	public Text getPaidText() {
		return paidText;
	}

	public void setPaidText(Text paidText) {
		this.paidText = paidText;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		if (customer != null) {
			this.customer = customer;
		}
	}

	public Table getTable() {
		return table;
	}

	public String getRcpcode() {
		return rcpcode;
	}

	public void setRcpcode(String rcpcode) {
		if (rcpcode != null) {
			if (rcpcode instanceof String) {
				this.rcpcode = (String) rcpcode;
			} else {
				try {
					this.rcpcode = rcpcode.toString();
				} catch (Exception e) {
				}
			}
		}
	}

	public Integer getCodeid() {
		return codeid;
	}

	public void setCodeid(Integer codeid) {
		this.codeid = codeid;
	}

	private void logProduct(Product product, Map<String, Object> params,
			String actionname, Transaction transaction, Double xquantity)
			throws Exception {

		try {

			if (product != null) {
				ProductLog plog = new ProductLogModel();

				plog.copyProduct(product);
				plog.setStatus(AppConstant.STATUS_ACTIVE);
				plog.setActionname(actionname);

				if (xquantity == null) {
					plog.setXquantity(0.0);
				} else {
					plog.setXquantity(xquantity);
				}

				List<ProductLog> plogs = session
						.createCriteria(ProductLogModel.class)
						.add(Expression.eq(ProductLog.FLD_PRODUCT, product))
						.addOrder(Order.desc(ProductLog.FLD_VERSION))
						.setMaxResults(1).list();
				if (plogs != null && !plogs.isEmpty()) {
					plog.setVersion(plogs.get(0).getVersion() + 1);
				} else {
					plog.setVersion(1);
				}

				if (params.get(AppConstant.USER) != null) {
					User user = (User) params.get(AppConstant.USER);
					Employee employee = user.getEmployee();

					Date today = new Date();
					plog.setCrtby(employee.getId());
					plog.setCrtdate(today);
					plog.setUpdby(employee.getId());
					plog.setUpddate(today);
				}

				if (transaction != null) {
					plog.setTransaction(transaction);
				}

				session.save(plog);

			}

		} catch (Exception e) {
			throw e;
		}
	}

	private void doAddProduct(String sku) {
		try {
			Product product = doRetrieveProduct(sku);
			Course course = doRetrieveCourse(sku);
			Treatment treatment = doRetrieveTreatment(sku);

			Double qty = new Double(0.0);
			try {
				qty = new Double(qtyText.getText());
			} catch (Exception nfe) {
			}
			if (product.getId() != null) {
				doAddItem(product, qty);
			} else if (course.getId() != null) {
				doAddItem(course, qty);
			} else if (treatment.getId() != null) {
				doAddItem(treatment, qty);
			} else {
				message(getShell(), "No Product/Course/Treatment Found",
						"No product/course/treatment found for this SKU.",
						SWT.ICON_WARNING | SWT.OK);
			}
		} catch (Exception e) {
			message(getShell(), "Unable to add product.",
					"Unable to add product.");
			log.error("Unable to add product.", e);
			e.printStackTrace();
		}
	}

	private void doAddItem(BizModel item, Double qty) {
		boolean isDuplicateItem = false;
		Product product = null;
		Course course = null;
		Treatment treatment = null;
		int itemType = 0; // 1-Product, 2-Course, 3-Treatment
		Double itemQty = new Double(0);

		if (item instanceof Product) {
			itemType = 1;
			product = (Product) item;
			itemQty = product.getQuantity();
		} else if (item instanceof Course) {
			itemType = 2;
			course = (Course) item;
			itemQty = course.getQuantity();
		} else if (item instanceof Treatment) {
			itemType = 3;
			treatment = (Treatment) item;
			itemQty = treatment.getQuantity();
		}

		for (Iterator<Transaction> iter = getTransactions().iterator(); iter
				.hasNext();) {
			Transaction transaction = iter.next();
			long transactionId = 0L, itemId = 0L;
			switch (itemType) {
			case 2:
				if (transaction.getCourse() != null) {
					transactionId = transaction.getCourse().getId().longValue();
				}
				itemId = course.getId().longValue();
				break;
			case 3:
				if (transaction.getTreatment() != null) {
					transactionId = transaction.getTreatment().getId()
							.longValue();
				}
				itemId = treatment.getId().longValue();
				break;
			default:
				if (transaction.getProduct() != null) {
					transactionId = transaction.getProduct().getId()
							.longValue();
				}
				itemId = product.getId().longValue();
				break;
			}
			if (transactionId == itemId) {
				isDuplicateItem = true;
				break;
			}
		}

		if (isDuplicateItem) {
			message(getShell(),
					"Duplicate Item.",
					"Item already entered in the receipt, please delete the other first.",
					SWT.ICON_WARNING | SWT.OK);
		} else {
			if (itemQty >= qty) {
				doAddTransactions(item, qty, useCustomerDiscountButton);
				doPopulateTable(table);
				doCalculateTotal();
				doCalculateChange();
				doClearAdd(skuText, qtyText);
			} else {
				message(getShell(), "Insufficient Balance",
						"Insufficent inventory balance, currenct balance is "
								+ df0.format(itemQty), SWT.ICON_WARNING
								| SWT.OK);
			}
		}
	}

	private void checkTableItems(Table table, boolean checked) {
		try {
			TableItem[] items = table.getItems();
			if (items != null && items.length > 0) {
				for (int i = 0; i < items.length; i++) {
					TableItem item = items[i];
					if (item.getData() != null) {
						item.setChecked(checked);
					}
				}
			}
		} catch (Exception e) {
			log.error("Unable to check all table items.", e);
		}
	}
}
